﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace SadlandVillage.Core
{
    public class MessageBox
    {
        #region Members and Properties
        public string Text { get; set; }
        public Vector2 Position { get; set; }
        public int Lines { get; set; }
        public int Columns { get; set; }
        public Color BackColor { get; set; }
        public Color ForeColor { get; set; }
        public bool DrawShadow { get; set; }
        public string SpeakerName { get; set; }

        private List<string> textLines;
        private SpriteFont font;
        private SpriteFont speakerFont;
        private int lineOffset;
        private Texture2D boxTexture;
        private int margin = 12;

        private ContentManager content { get; set; }
        private SpriteBatch spriteBatch { get; set; }
        #endregion

        public event EventHandler Blur;

        #region Construtores
        public MessageBox(ContentManager content, SpriteBatch spriteBatch,
            string text, Vector2 position, int lines, int columns)
        {
            this.Text = text;
            this.Position = position;
            this.Lines = lines;
            this.Columns = columns;

            this.content = content;
            this.spriteBatch = spriteBatch;
            textLines = new List<string>();

            BackColor = Color.Blue;
            ForeColor = Color.White;
        }

        public MessageBox(ContentManager content, SpriteBatch spriteBatch,
            string text, Vector2 position, int lines, int columns,
            Color backColor, Color foreColor)
            :this(content, spriteBatch, text, position, lines, columns)
        {

            BackColor = backColor;
            ForeColor = foreColor;
        }

        public MessageBox(ContentManager content, SpriteBatch spriteBatch)            
        {
            this.content = content;
            this.spriteBatch = spriteBatch;
        }

        #endregion

        public void LoadContent()
        {
            font = content.Load<SpriteFont>(@"MessageBox\DefaultText");
            speakerFont = content.Load<SpriteFont>(@"MessageBox\SpeakerName");
            boxTexture = content.Load<Texture2D>(@"MessageBox\mbox");

            string[] allWords = this.Text.Split(' ');
            textLines = ExtractLines(allWords);

        }

        private int GetHeight()
        {
            return Convert.ToInt32(Lines * font.MeasureString("X").Y);
        }

        private int GetWidth()
        {
            return Convert.ToInt32(Columns * font.MeasureString("X").X);
        }      

        private List<string> ExtractLines(string[] allWords)
        {
            var result = new List<string>();
            StringBuilder sbLine = new StringBuilder();
            foreach (string word in allWords)
            {
                if ((sbLine.Length + word.Length + 1) >= Columns)
                {
                    result.Add(sbLine.ToString());
                    sbLine = new StringBuilder();
                }

                sbLine.Append(word);
                sbLine.Append(" ");
            }

            result.Add(sbLine.ToString());

            return result;
        }

        public void Update(GameTime gameTime)
        {
            if (Input.KeyPressed(Keys.Down))
            {
                if ((lineOffset + Lines) < textLines.Count)
                {
                    lineOffset += Lines;
                }
                else
                {
                    LostFocus();
                }
            }
            if (Input.KeyPressed(Keys.Up))
            {
                if (lineOffset > 0)
                {
                    lineOffset -= Lines;
                }
            }
        }

        private void LostFocus()
        {
            if (Blur != null)
            {
                lineOffset = 0;
                Blur(this, null);
            }
        }

        public void Draw(GameTime gameTime)
        {            
            
            int offset = margin;
            spriteBatch.Begin();
            spriteBatch.Draw(boxTexture, GetRectangle(), BackColor);
            for (int i = lineOffset; i < lineOffset + Lines && i < textLines.Count; i++)
            {
                string textToDraw = textLines[i];
                Vector2 positionToDraw = Position + new Vector2(margin, offset);
                if ((i != textLines.Count - 1) && (i%Lines == Lines-1))
                    textToDraw += "...";
                if (DrawShadow)
                {
                    spriteBatch.DrawString(font, textToDraw, positionToDraw + new Vector2(-1,1), Color.Black);
                }
                if (SpeakerName != null)
                {
                    spriteBatch.DrawString(speakerFont, SpeakerName, Position + new Vector2(20, -10), ForeColor);
                }
                spriteBatch.DrawString(font, textToDraw, positionToDraw, ForeColor);
                
                
                offset += font.LineSpacing;
            }
            spriteBatch.End();
        }

        private Rectangle GetRectangle()
        {            
            int height = GetHeight() + 2*margin;
            int width = GetWidth() + margin;
            int x = Convert.ToInt32(Position.X);
            int y = Convert.ToInt32(Position.Y);

            return new Rectangle(x, y, width, height);
        }
    }
}
